//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   Field.hh
 * \author Jeremy Roberts
 * \date   Jul 6, 2011
 * \brief  Base field for representing data
 * \note   Copyright (C) 2011 Jeremy Roberts.  Derived from Denovo.
 */
//---------------------------------------------------------------------------//
// $Rev:: 119                                           $:Rev of last commit
// $Author:: j.alyn.roberts@gmail.com                   $:Author of last commit
// $Date:: 2011-07-13 00:57:22 +0000 (Wed, 13 Jul 2011) $:Date of last commit
//---------------------------------------------------------------------------//


#ifndef FIELD_HH_
#define FIELD_HH_

#include <vector>
#include <typeinfo> // defines types used with operators typeid and dynamic_cast

#include "../utilities/DBC.hh"

namespace slabtran
{

//===========================================================================//
/*!
 * \class Field
 * \brief Abstract base class of all Field types.
 *
 * Field types may use this class as a base class.  It defines the types and
 * member functions for a Container concept (see section 9.1.1 of Austern,
 * "Generic Programming and the STL").  In addition, this class defines
 * operator[], which assumes that all Field types are random access.  The
 * storage is contiguous.
 *
 * One departure from the Container concept is that assignment in Field
 * is only valid for Field types that have the same number of elements.
 *
 * \param T   The type of each field element (may be accessed via value_type).
 */
/*!
 * \example test/testField.cc
 *
 * Test of Field.
 */
//===========================================================================//

template <class T>
class Field
{
  public:

    // >>> NESTED CLASSES AND TYPEDEFS

    //! Underlying data storage type.
    typedef std::vector<T> Field_Storage;

    //@{
    //! These typedefs are needed for the Container concept
    typedef T                                       value_type;
    typedef T&                                      reference;
    typedef const T&                                const_reference;
    typedef typename Field_Storage::pointer         pointer;
    typedef typename Field_Storage::const_pointer   const_pointer;
    typedef typename Field_Storage::iterator        iterator;
    typedef typename Field_Storage::const_iterator  const_iterator;
    typedef typename Field_Storage::size_type       size_type;
    typedef typename Field_Storage::difference_type difference_type;
    //@}

    // >>> CREATORS

    // NO DEFAULT CONSTRUCTOR
    // Field();

    // Constructor.
    inline explicit Field(const size_type n, const T v = T());

    // Range constructor.
    inline Field(const_iterator b, const_iterator e);

    // Copy constructor
    inline Field(const Field &rhs);

    // Destructor
    inline virtual ~Field();

    // MANIPULATORS

    // Assignment operator to a Field
    inline Field& operator=(const Field &rhs);

    // ACCESSORS

    // Returns field value at index i.
    inline reference operator[](const size_type i);

    // Returns constant field value at index i.
    inline const_reference operator[](const size_type i) const;

    //! Begin iterator.
    iterator begin() { return d_values.begin(); }

    //! Begin constant iterator.
    const_iterator begin() const { return d_values.begin(); }

    //! End iterator.
    iterator end() { return d_values.end(); }

    //! End constant iterator.
    const_iterator end() const { return d_values.end(); }

    //! Number of field values.
    size_type size() const { return d_values.size(); }

    //! Returns true if there are no field values.
    bool empty() const { return d_values.empty(); }

    // Swaps the field data with \a b.
    inline void swap(Field<T> &b);

    // For bounds checking.
    inline bool valid_index(const size_type i) const;

  protected:

    // >>> DATA

    Field_Storage d_values;
};

} // end namespace slabtran

//---------------------------------------------------------------------------//
// INLINE FUNCTIONS
//---------------------------------------------------------------------------//

#include "tran/Field.i.hh"

#endif /* FIELD_HH_ */

//---------------------------------------------------------------------------//
//              end of Field.hh
//---------------------------------------------------------------------------//
